package com.qiangesoft.pay.app.controller;

import cn.hutool.extra.servlet.ServletUtil;
import com.qiangesoft.pay.app.service.IPayService;
import com.qiangesoft.pay.app.service.IRefundService;
import com.wechat.pay.java.core.http.Constant;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@RestController
@RequestMapping("/wxApp")
public class WxAppPayController {

    @Autowired
    private IPayService payService;

    @Autowired
    private IRefundService refundService;

    @Autowired
    private NotificationParser parser;

    @PostMapping("/pay")
    public PrepayWithRequestPaymentResponse pay(@RequestParam String openid,
                                                @RequestParam String outTradeNo,
                                                @RequestParam Integer totalFee,
                                                @RequestParam String description) {
        return payService.pay(openid, outTradeNo, totalFee, description);
    }

    @GetMapping("/pay/{outTradeNo}")
    public Transaction queryPay(@PathVariable String outTradeNo) {
        return payService.query(outTradeNo);
    }

    @PostMapping("/pay/notify")
    public void payNotify(HttpServletRequest request) {
        try {
            // 请求体信息
            String body = ServletUtil.getBody(request);

            // 验签、解密并转换成Transaction
            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                    .serialNumber(request.getHeader(Constant.WECHAT_PAY_SERIAL))
                    .nonce(request.getHeader(Constant.WECHAT_PAY_NONCE))
                    .signature(request.getHeader(Constant.WECHAT_PAY_SIGNATURE))
                    .timestamp(request.getHeader(Constant.WECHAT_PAY_TIMESTAMP))
                    .signType(request.getHeader("Wechatpay-Signature-Type"))
                    .body(body)
                    .build();
            Transaction transaction = parser.parse(requestParam, Transaction.class);

            // 业务回调
            payService.notify(transaction);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostMapping("/refund")
    public void refund(@RequestParam String outTradeNo,
                       @RequestParam String outRefundNo,
                       @RequestParam String refundReason,
                       @RequestParam Long totalFee,
                       @RequestParam Long refundFee) {
        refundService.refund(outTradeNo, outRefundNo, refundReason, totalFee, refundFee);
    }

    @PostMapping("/refund/{outRefundNo}")
    public Refund queryRefund(@PathVariable String outRefundNo) {
        return refundService.query(outRefundNo);
    }

    @PostMapping("/refund/notify")
    public void refundNotify(HttpServletRequest request) {
        try {
            // 请求体信息
            String body = ServletUtil.getBody(request);

            // 验签、解密并转换成Transaction
            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                    .serialNumber(request.getHeader(Constant.WECHAT_PAY_SERIAL))
                    .nonce(request.getHeader(Constant.WECHAT_PAY_NONCE))
                    .signature(request.getHeader(Constant.WECHAT_PAY_SIGNATURE))
                    .timestamp(request.getHeader(Constant.WECHAT_PAY_TIMESTAMP))
                    .signType(request.getHeader("Wechatpay-Signature-Type"))
                    .body(body)
                    .build();
            Refund refund = parser.parse(requestParam, Refund.class);

            // 业务回调
            refundService.notify(refund);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
